///////////////////////////////////////////////////////////////////////////////
// File Name:   vga_timer.v
//
// Author:      Cody Cziesler
//
// Description: The timing portion of the vga
//
// OUT:    ----------OOOOOOOOOO----------
// VS/HS:  ----__------------------__----
//            |  |  |          |  | 
//            |PW|BP|COLS/LINES|FP|
//            |                   |
//            |<--TOTAL CLOCKS--->|
//
// PW = Pulse width
// BP = Back porch
// FP = Front porch
// COLS/LINES = Where the data is outputted
//
///////////////////////////////////////////////////////////////////////////////

module vga_timer (
  input   wire         clk,
  input   wire         rst_n,
  output  wire         v_sync,
  output  wire         h_sync,
  output  wire  [10:0] x_pixel,
  output  wire  [10:0] y_pixel
);

//-----------------------------------------------------------------------------
// Numbers below are for a 25 MHz clock @ 640x800
//   Number of clock pulses for horizontal, number of horizontal lines for vertical
//-----------------------------------------------------------------------------
parameter HSYNC_PW       = 10'd96;
parameter HSYNC_BP       = 10'd48;
parameter COLS           = 10'd640;
parameter HSYNC_FP       = 10'd16;
parameter TOTAL_H_CLOCKS = HSYNC_PW + HSYNC_BP + COLS + HSYNC_FP;

parameter VSYNC_PW       = 10'd2;
parameter VSYNC_BP       = 10'd29;
parameter LINES          = 10'd480;
parameter VSYNC_FP       = 10'd10;
parameter TOTAL_V_CLOCKS = VSYNC_PW + VSYNC_BP + LINES + VSYNC_FP;

parameter POLARITY       = 1'b1;

//-----------------------------------------------------------------------------
// h_pulse is a pulse the width of a clock period. It is high whenever 
//   horiz_count is zero. Used for counting the lines
//-----------------------------------------------------------------------------
wire h_pulse;

//-----------------------------------------------------------------------------
// Registers to hold the pixel count
//-----------------------------------------------------------------------------
reg [10:0] x_pixel_r;
reg [10:0] y_pixel_r;

//-----------------------------------------------------------------------------
// The count registers for horizontal and verical counters
//-----------------------------------------------------------------------------
reg [10:0] horiz_count;
reg [10:0] vert_count;

//-----------------------------------------------------------------------------
// Assign the output wire ports so that we are not reading an output port
//-----------------------------------------------------------------------------
assign y_pixel = y_pixel_r;
assign x_pixel = x_pixel_r;

//-----------------------------------------------------------------------------
// h_sync is when horiz_count is between 0 and HSYNC_PW
// v_sync is when vert_count  is between 0 and VSYNC_PW
//-----------------------------------------------------------------------------
assign v_sync = (vert_count  < VSYNC_PW) ? POLARITY : ~POLARITY;
assign h_sync = (horiz_count < HSYNC_PW) ? POLARITY : ~POLARITY;

//-----------------------------------------------------------------------------
// h_pulse goes high whenever horiz_count == 0
//-----------------------------------------------------------------------------
assign h_pulse = (horiz_count == 11'h0) ? 1'b1 : 1'b0;

//-----------------------------------------------------------------------------
// x_pixel_r is the COLS part of horiz_count
//-----------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
  if (!rst_n) begin
    x_pixel_r   <= 11'h0;
  end else begin
    if (horiz_count == (TOTAL_H_CLOCKS - 1'b1)) begin
      x_pixel_r <= 11'h0;
    end else if ((horiz_count >= (HSYNC_PW + HSYNC_BP)) && (horiz_count < (HSYNC_PW + HSYNC_BP + COLS))) begin
      x_pixel_r <= x_pixel_r + 1'b1;
    end
  end
end

//-----------------------------------------------------------------------------
// y_pixel_r is the LINES part of vert_count
//-----------------------------------------------------------------------------
always @(posedge h_pulse or negedge rst_n) begin
  if (!rst_n) begin
    y_pixel_r   <= 11'h0;
  end else begin
    if (vert_count == (TOTAL_V_CLOCKS - 1'b1)) begin
      y_pixel_r <= 11'h0;
    end else if ( (vert_count  >= (VSYNC_PW + VSYNC_BP)) && (vert_count  < (VSYNC_PW + VSYNC_BP + LINES)) ) begin
      y_pixel_r <= y_pixel_r + 1'b1;
    end
  end
end

//-----------------------------------------------------------------------------
// Always block for horizontal timing
//-----------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
  if (!rst_n) begin
    horiz_count    <= 11'b0;
  end else begin
    if (horiz_count == (TOTAL_H_CLOCKS - 1'b1)) begin
      horiz_count  <= 11'b0;
    end else begin
      horiz_count  <= horiz_count + 1'b1;
    end
  end
end

//-----------------------------------------------------------------------------
// Always block for vertical timing
//-----------------------------------------------------------------------------
always @(posedge h_pulse or negedge rst_n) begin
  if (!rst_n) begin
    vert_count     <= 11'b0;
  end else begin
    if (vert_count == (TOTAL_V_CLOCKS - 1'b1)) begin
      vert_count   <= 11'b0;
    end else begin
      vert_count   <= vert_count + 1'b1;
    end
  end
end

endmodule
